#include <LitStdAfx.h>
#include "LitPlane.h"

namespace Lit
{
	Plane::Plane(PlaneAxis ax, const std::string &name, const Vec2 &size)
		: Movable(MT_PLANE, name), mSize(size), mAxis(ax)
	{
	}


	Plane::~Plane(void)
	{
	}
	void Plane::_add( const Vec3& pos, const Vec2 &uv, const Vec3& normal )
	{
		mObject->position(pos);
		if( normal != Ogre::Vector3::ZERO )
			mObject->normal( normal.normalisedCopy() );
		mObject->textureCoord(uv);
	}
	const std::string& Plane::getMeshName() const{ return mMeshName; }
	OgreMeshPtr Plane::getMesh() const{ return mMesh; }
	
	OgreManualObjPtr Plane::_createXZ( )
	{
		Ogre::MaterialPtr mat = _createMaterial( );
		mObject = mMgr->createManualObject("MO_"+mName);
		mObject->begin( mat->getName(), Ogre::RenderOperation::OT_TRIANGLE_LIST );
		_add( Vec3::ZERO				, Vec2(0.0,0.0),	Vec3::UNIT_Y );
		_add( Vec3(mSize.x,0,0)			, Vec2(1.0,0.0),	Vec3::UNIT_Y );
		_add( Vec3(mSize.x,0,-mSize.y)	, Vec2(1.0,1.0),	Vec3::UNIT_Y );

		_add( Vec3(mSize.x,0,-mSize.y)	, Vec2(1.0,1.0),	Vec3::UNIT_Y );
		_add( Vec3(0,0,-mSize.y)		, Vec2(0.0,1.0),	Vec3::UNIT_Y );
		_add( Vec3::ZERO				, Vec2(0.0,0.0),	Vec3::UNIT_Y );
		mObject->end();
		return mObject;
	}
	OgreManualObjPtr Plane::_createXY( )
	{
		Ogre::MaterialPtr mat = _createMaterial( );
		mObject = mMgr->createManualObject("MO_"+mName);
		mObject->begin( mat->getName(), Ogre::RenderOperation::OT_TRIANGLE_LIST );
		_add( Vec3::ZERO				, Vec2(0.0,0.0),	Vec3::UNIT_Y );
		_add( Vec3(mSize.x,0,0)			, Vec2(1.0,0.0),	Vec3::UNIT_Y );
		_add( Vec3(mSize.x,-mSize.y,0)	, Vec2(1.0,1.0),	Vec3::UNIT_Y );

		_add( Vec3(mSize.x,-mSize.y,0)	, Vec2(1.0,1.0),	Vec3::UNIT_Y );
		_add( Vec3(0,-mSize.y,0)		, Vec2(0.0,1.0),	Vec3::UNIT_Y );
		_add( Vec3::ZERO				, Vec2(0.0,0.0),	Vec3::UNIT_Y );
		mObject->end();
		return mObject;
	}
	OgreManualObjPtr Plane::_createYZ( )
	{
		Ogre::MaterialPtr mat = _createMaterial( );
		mObject = mMgr->createManualObject("MO_"+mName);
		mObject->begin( mat->getName(), Ogre::RenderOperation::OT_TRIANGLE_LIST );
		_add( Vec3::ZERO				, Vec2(0.0,0.0),	Vec3::UNIT_Y );
		_add( Vec3(0,mSize.x,0)			, Vec2(1.0,0.0),	Vec3::UNIT_Y );
		_add( Vec3(0,mSize.x,-mSize.y)	, Vec2(1.0,1.0),	Vec3::UNIT_Y );

		_add( Vec3(0,mSize.x,-mSize.y)	, Vec2(1.0,1.0),	Vec3::UNIT_Y );
		_add( Vec3(0,0,-mSize.y)		, Vec2(0.0,1.0),	Vec3::UNIT_Y );
		_add( Vec3::ZERO				, Vec2(0.0,0.0),	Vec3::UNIT_Y );
		mObject->end();
		return mObject;
	}
	OgreMaterialPtr Plane::_createMaterial( ){
		auto res = Ogre::MaterialManager::getSingleton().createOrRetrieve( "Material_"+mName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME );
		OgreMaterialPtr mat(res.first);
		Color col;
		switch( mAxis )
		{
			case PLANE_XY: col = Color( 0.0f, 0.15f, 0.53f ); break; // blue
			case PLANE_XZ: col = Color( 0.0f, 0.53f, 0.15f ); break; // green
			case PLANE_YZ: col = Color( 0.53f, 0.15f, 0.15f ); break; // red-orange
			case PLANE_NONE:
			default:	// yellow
				col = Color( 1.0f, 0.65f, 0.65f );
		};
		if( res.second )
		{
			Ogre::Pass * p = mat->createTechnique()->createPass();
			p->setLightingEnabled( true );
			p->setDepthCheckEnabled( false );
			p->setDepthWriteEnabled( false );
			p->setDiffuse( Ogre::ColourValue( col.r, col.g, col.b, 0.45f ) );
			p->setAmbient( Ogre::ColourValue( col.r, col.g, col.b, 0.45f ) );
			p->setSpecular( Ogre::ColourValue( col.r, col.g, col.b, 0.45f ) );
			p->setSelfIllumination( 0.3f, 0.3f, 0.3f );
		}
		if( !mat->isLoaded() ) mat->load();
		return mat;
	}
	void Plane::create(OgreSceneManagerPtr mgr)
	{
		mMgr = mgr;
		mMeshName = "PlaneMesh_"+mName;
		Ogre::MaterialPtr mat = _createMaterial( );
		switch( mAxis )
		{
		case PLANE_XZ: _createXZ(); break;
		case PLANE_XY: _createXY(); break;
		case PLANE_YZ: _createYZ(); break;
		case PLANE_NONE:
		default:
			throw Lit::ImplementationMissing( trPlaneAxis( mAxis ), EXC_LOC );
		};

		mMesh = mObject->convertToMesh(mMeshName);
		mEntity = mgr->createEntity( mName, mMeshName );
		mNode = mgr->getRootSceneNode()->createChildSceneNode();
		mNode->attachObject( *mEntity );
		mEntity->setMaterial( mat );
	}
	void Plane::destroy()
	{
		if( mEntity ){
			mNode->detachAllObjects();
			mMgr->destroyEntity(*mEntity);
			mMgr->destroySceneNode( *mNode );
			mEntity.swap( NULL );
		}
		if( !mMesh.isNull() )
		{
			Ogre::MeshManager::getSingletonPtr()->unload( mMeshName );
			Ogre::MeshManager::getSingletonPtr()->remove( mMeshName );
			mMesh.setNull();
		}
		if( mObject )
		{
			mMgr->destroyManualObject( *mObject );
			mObject = NULL;
		}
	}
	void Plane::exportAttribs( TiXmlElement * elem )
	{
	}
	void Plane::importAttribs( TiXmlElement * elem )
	{
	}
}